﻿using Newtonsoft.Json;
using SmartForm.Util;
using SmartlForm.Common;
using SmartlForm.DAL;
using SmartlForm.Model;
using SmartlForm.SimpleCrawler;
using SmartlForm.SimpleCrawler.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;

namespace SmartlForm.NetJs
{
    /// <summary>
    /// 爬虫接口
    /// </summary>
    public partial class BowContainer
    {
        private long taskId = 1;
        /// <summary>
        /// 线程数量
        /// </summary>
        private readonly static int ThreadNumber = 10;
        /// <summary>
        /// delay 延时计时器
        /// </summary>
        private static List<TimerDic> timers = new List<TimerDic>();

        /// <summary>
        /// schedule 调度间隔计时器
        /// </summary>
        private static List<TimerDic> scheduleList = new List<TimerDic>();

        /// <summary>
        /// 爬虫延时执行Timer与抓取规则调度Timer
        /// </summary>
        private static System.Timers.Timer delayTimer, scheduleTimer;
        /// <summary>
        /// 抓取规则内容
        /// </summary>
        private static List<SiteModel> SiteConfigs = new List<SiteModel>();

        public void startSmartCrawler()
        {
            new Thread(initTaskList).Start();
        }

        public void initTaskList()
        {
            var path = Application.StartupPath + "\\Config\\新闻.xml";
            SiteModel siteConfig = XmlHelper.DESerializerByPath<SiteModel>(path);
            siteConfig.accountId = getAccountId();
            //获取关键词
            List<Keyword> list = KeywordDao.Instance.GetList(getAccountId());
            foreach (var item in list)
            {
                addStartOne(item, siteConfig);
            }
        }

        public void stopTask(object obj)
        {
            Console.WriteLine("stopTask obj：" + JsonConvert.SerializeObject(obj));
            var item = (Keyword)obj;

            delayTimer = timers.FirstOrDefault(d => d.ConfigId == item.id).Timer;
            if (delayTimer != null)
            {
                //停止任务队列
                delayTimer.Stop();
            }
            scheduleTimer = scheduleList.FirstOrDefault(d => d.ConfigId == item.id).Timer;
            if (scheduleTimer != null)
            {
                //停止调动队列
                scheduleTimer.Stop();
            }
        }

        public void initTask(object obj)
        {
            Console.WriteLine("initTask obj：" + JsonConvert.SerializeObject(obj));
            var item = (Keyword)obj;
            var path = Application.StartupPath + "\\Config\\新闻.xml";
            SiteModel siteConfig = XmlHelper.DESerializerByPath<SiteModel>(path);
            siteConfig.accountId = getAccountId();
            addStartOne(item, siteConfig);
        }

        public void addStartOne(Keyword item, SiteModel siteConfig)
        {
            var itemConfig = new SiteModel();
            itemConfig.Id = item.id;
            itemConfig.accountId = siteConfig.accountId;
            itemConfig.Delay = siteConfig.Delay;
            itemConfig.Encoding = siteConfig.Encoding;
            itemConfig.Schedule = siteConfig.Schedule;
            itemConfig.Targets = siteConfig.Targets;
            itemConfig.Type = item.name;
            itemConfig.Timeout = siteConfig.Timeout;
            itemConfig.Url = siteConfig.Url.Replace("{keyword}", item.name);
            SiteConfigs.Add(itemConfig);

            //初始化任务
            SmartCrawler.Create(itemConfig.Url, itemConfig);

            //根据调度时间重置抓取状态
            scheduleList.Add(new TimerDic() { ConfigId = itemConfig.Id, TaskId = taskId, Timer = new System.Timers.Timer(), IsRunning = true });
            scheduleTimer = scheduleList.FirstOrDefault(d => d.ConfigId == itemConfig.Id).Timer;
            scheduleTimer.Interval = itemConfig.Schedule;
            scheduleTimer.AutoReset = true;
            //传参
            scheduleTimer.SynchronizingObject = new Button() { Text = itemConfig.ToString() };
            scheduleTimer.Elapsed += new ElapsedEventHandler(ScheduleTimerHandle);
            scheduleTimer.Start();

            //将各个关键词任务添加任务队列
            timers.Add(new TimerDic() { ConfigId = itemConfig.Id, TaskId = taskId, Timer = new System.Timers.Timer() });
            delayTimer = timers.FirstOrDefault(d => d.ConfigId == itemConfig.Id).Timer;
            delayTimer.Interval = itemConfig.Delay;
            delayTimer.AutoReset = true;
            delayTimer.SynchronizingObject = new Button() { Text = itemConfig.Id.ToString() };
            delayTimer.Elapsed += new ElapsedEventHandler(spiderStart);
            delayTimer.Start();
        }

        /// <summary>
        /// 开始任务
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void spiderStart(object source, ElapsedEventArgs e)
        {
            try
            {
                var configId = long.Parse(((Button)((System.Timers.Timer)source).SynchronizingObject).Text);
                Console.WriteLine("【" + configId.ToString() + "】spiderStart Time：" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                for (int i = 0; i < ThreadNumber; i++)
                {
                    if (SmartCrawler.urlQueue != null && SmartCrawler.urlQueue.Count > 0 && SmartCrawler.urlQueue.ContainsKey(configId) && SmartCrawler.urlQueue[configId] != null && SmartCrawler.urlQueue[configId].Count > 0)
                    {
                        var url = SmartCrawler.urlQueue[configId].Dequeue();
                        if (!string.IsNullOrEmpty(url))
                        {
                            var siteConfig = SiteConfigs.FirstOrDefault(d => d.Id == configId);
                            Console.WriteLine("spiderStart start：" + siteConfig.Url);
                            SmartCrawler.Create(url, siteConfig);
                        }
                    }
                    else
                    {
                        //队列暂无数据，退出下列循环
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("spiderStart error：" + ex.ToString());
            }
        }

        /// <summary>
        /// 重新抓取调度
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void ScheduleTimerHandle(object source, ElapsedEventArgs e)
        {
            try
            {
                var configId = long.Parse(((Button)((System.Timers.Timer)source).SynchronizingObject).Text);
                Console.WriteLine("【" + configId.ToString() + "】ScheduleTimerHandle Time：" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                if (SmartCrawler.urlHistory.ContainsKey(configId))
                {
                    //重置历史记录
                    SmartCrawler.urlHistory[configId] = new List<string>();

                    //重启中
                    var siteConfig = SiteConfigs.FirstOrDefault(d => d.Id == configId);
                    SmartCrawler.Create(siteConfig.Url, siteConfig);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

    }
}
